﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using Gencode.PrsCommon.App;
using Gencode.PrsCommon.Data.Dienst;

namespace Gencode.PrsCommon.Data.Plan
{
    public class Grid
    {
        protected Row[] rows;
        DataTable m_data;
        DataView m_personen;
        SaldoTable m_saldoTable;

		/// <summary>
		/// Creates a Grid of Data for the plan with the given planid
		/// </summary>
		/// <param name="planID">planid of the plan to be created</param>
		public Grid(int planID)
		{
			PlanID = planID;
            PlanName = PlanData.GetPlanName(planID);
			CreateRows(planID);
		}

		/// <summary>
		/// Creates the Data for the Plan with the current planid
		/// </summary>
		private void CreateRows(int planID)
		{

			if (rows != null)
				rows = null;

            m_personen = PlanData.GetPersonenInPlan(planID);
            int rowcount = m_personen.Count;

            if (ShowDaysInPlan)
            {
                DataView abteilungen = PlanData.GetAbteilungenInSchema(PlanData.GetPlanSchemaID(planID));
                rowcount += abteilungen.Count;
                abteilungen.Dispose();
            }
            
            rows = new Row[rowcount];

            int i = 0;
            foreach (DataRowView dvrow in m_personen)
            {
                int prsid = int.Parse(dvrow["prsid"].ToString());

                Row.ROWTYPE rt;
                if(prsid == 0)
                    rt = Row.ROWTYPE.Abteilung;
                else if(prsid < 0)
                    rt = Row.ROWTYPE.Leer;
                else
                    rt = Row.ROWTYPE.Person;

                //allways show days before abteilung
                if (prsid == 0 && ShowDaysInPlan)
                {
                    Row r = new Row
                    {
                        PrsID = -2,
                        PersonName = string.Empty,
                        AbteilungID = int.Parse(dvrow["abteilungid"].ToString()),
                        AbteilungName = dvrow["abteilungname"].ToString(),
                        PrsSchemaID = 0,
                        Von = DateUtil.ConvertSqlToDate(dvrow["von"].ToString()),
                        Bis = DateUtil.ConvertSqlToDate(dvrow["bis"].ToString()),
                        Pensum = 0,
                        ARGB = System.Drawing.Color.FromName("Gainsboro").ToArgb(),
                        PlanID = planID,
                        RowType = Row.ROWTYPE.Taganzeige
                    };
                    r.InitData();
                    rows[i] = r;
                    i++;
                }
                
                Row row = new Row
                {
                    PrsID = prsid,
                    PersonName = dvrow["nachname"].ToString() + " " + dvrow["name"].ToString(),
                    AbteilungID = int.Parse(dvrow["abteilungid"].ToString()),
                    AbteilungName = dvrow["abteilungname"].ToString(),
                    PrsSchemaID = int.Parse(dvrow["prsschemaid"].ToString()),
                    Von = DateUtil.ConvertSqlToDate(dvrow["von"].ToString()),
                    Bis = DateUtil.ConvertSqlToDate(dvrow["bis"].ToString()),
                    Pensum = int.Parse(dvrow["pensum"].ToString()),
                    ARGB = int.Parse(dvrow["rgb"].ToString()),
                    PlanID = planID,
                    RowType = rt
                };
                row.InitData();
                rows[i] = row;
                i++;
            }
		}

		/// <summary>
		/// Columns to be added before the data of the plan grid
		/// </summary>
		public int PreColumnCount = 0;

        protected virtual DataTable CreateDataTable()
        {
            DataTable dv = new DataTable();
            int preCount = 1;
            if(PlanOption.ShowPersonPercentInPlan == 1)
                preCount++;

            //Create header
            dv.Columns.Add("Person", typeof(string));

            if (preCount > 1)//Show Prozent
                dv.Columns.Add("Proz", typeof(int));

            for (int i = 0; i < rows[0].Cells.Length; i++)
            {
                dv.Columns.Add(DateUtil.GetDay(this[0, i].Datum), typeof(string));
            }

            DataRow row;

            //1. Row
            /*if (ShowDaysInPlan)
            {
                row = dv.NewRow();
                int y = int.Parse(DateUtil.GetYear(this[0, 0].Datum));
                int m = int.Parse(DateUtil.GetMonth(this[0, 0].Datum));

                for (int i = 0; i < rows[0].Cells.Length; i++)
                    row[i + preCount] = DateUtil.DayInWeek(y, m, i + 1);

                dv.Rows.Add(row);
            }*/

            //Data rows
            for (int r = 0; r < rows.Length; r++)
            {
                row = dv.NewRow();

                if(rows[r].RowType == Row.ROWTYPE.Abteilung)
                    row[0] = rows[r].AbteilungName;
                else if (rows[r].RowType == Row.ROWTYPE.Person)
                    row[0] = rows[r].PersonName;

                if (preCount > 1)
                    if (rows[r].RowType == Row.ROWTYPE.Person)
                        row[1] = rows[r].Pensum;

                for (int c = 0; c < rows[r].Cells.Length; c++)
                {
                    row[c + preCount] = rows[r][c].DienstName;
                }
                dv.Rows.Add(row);
            }
            
			Data = dv;
			//Set amount of rows before actual data
			PreColumnCount = preCount;

            return dv;
        }

        private void InitSaldoDataTable()
        {
            m_saldoTable = new SaldoTable();

            //1. Row
            //if (ShowDaysInPlan)
            //    m_saldoTable.AddItem();

            foreach (DataRowView row in m_personen)
            {
                if (int.Parse(row["prsid"].ToString()) > 0)
                {
                    m_saldoTable.AddItem(int.Parse(row["prsid"].ToString()),
                        PlanID,
                        int.Parse(row["abteilungid"].ToString()));
                }
                else
                {
                    if (ShowDaysInPlan && int.Parse(row["prsid"].ToString()) == 0)
                        m_saldoTable.AddItem();
                    m_saldoTable.AddItem();
                }
            }
        }

        /// <summary>
        /// Reloads a row of the Saldotable at the given index
        /// </summary>
        /// <param name="index">Index of row in Table</param>
        public void ReloadSaldoRow(int index, int headerRowCount)
        {
            m_saldoTable.UpdateRow(index, Rows[index].PrsID, PlanID, Rows[index].AbteilungID);
            //m_saldoTable.UpdateRow(index, int.Parse(m_personen[index - headerRowCount].Row["prsid"].ToString()),
            //    PlanID, int.Parse(m_personen[index - headerRowCount].Row["abteilungid"].ToString()));
        }

        public void RepositionRow(int rowIndex, int destinationIndex)
        {
            Row row = this[rowIndex];
            if (rowIndex < destinationIndex)
            {
                for (int i = rowIndex; i < destinationIndex; i++)
                {
                    this[i] = this[i + 1];
                }
            }
            else
            {
                for (int i = rowIndex; i > destinationIndex; i--)
                {
                    this[i] = this[i - 1];
                }
            }
            this[destinationIndex] = row;

            //reposition in datatable
            DataRow dr = Data.NewRow();
            for (int i = 0; i < Data.Columns.Count; i++)
            {
                dr[i] = Data.Rows[rowIndex][i];
            }

            Data.Rows.RemoveAt(rowIndex);
            Data.Rows.InsertAt(dr, destinationIndex);

            //reposition in saldotable
            dr = SaldoDataTable.NewRow();
            for (int i = 0; i < SaldoDataTable.Columns.Count; i++)
            {
                dr[i] = SaldoDataTable.Rows[rowIndex][i];
            }

            SaldoDataTable.Rows.RemoveAt(rowIndex);
            SaldoDataTable.Rows.InsertAt(dr, destinationIndex);

            //save schema
            Gencode.Common.ActionLogger.Logger.LoggMessage(Gencode.Common.ActionLogger.MessageType.USER_EVENT, "Update schema in plan " + PlanID + " from Drag & Drop in plan)");

            PlanData.DeleteRowsFromSchema(SchemaID);
            int prsSchemaID = 1;
            for (int i = 0; i < Rows.Length; i++)
            {
                if (Rows[i].RowType != Row.ROWTYPE.Taganzeige)
                {
                    PlanData.SaveSchemaRow(
                        SchemaID, 
                        prsSchemaID, 
                        Rows[i].PrsID,
                        Rows[i].AbteilungID,
                        Rows[i].ARGB);

                    prsSchemaID++;
                }
            }
        }

		/// <summary>
		/// Returns the Row element at the given Index
		/// </summary>
		/// <param name="row">Index of Row</param>
		/// <returns>Row element at the given Index</returns>
		public Row this[int row]
		{
            get
            {
                return rows[row];
            }
            private set
            {
                rows[row] = value;
            }
		}

        /// <summary>
        /// Returns Cell element at given row and column
        /// </summary>
        /// <param name="row">Index of row</param>
        /// <param name="column">Index of column</param>
        /// <returns>Cell of given Index</returns>
        public Cell this[int row, int column]
        {
            get
            {
                return rows[row][column];
            }
        }

        public Row[] Rows
        {
            get
            {
                return rows;
            }
        }

		/// <summary>
		/// Returns the PlanID of the current plan
		/// </summary>
        public int PlanID
        {
            get;
            private set;
        }

        public string PlanName
        {
            get;
            private set;
        }

        /// <summary>
        /// DataTable of GridData
        /// </summary>
        public DataTable Data
        {
            get
            {
                if (m_data != null)
                    return m_data;

                return CreateDataTable();
            }
            protected set
            {
                m_data = value;
            }
        }

        public DataTable SaldoDataTable
        {
            get
            {
                if (m_saldoTable == null || m_saldoTable.Table == null)
                    InitSaldoDataTable();

                return m_saldoTable.Table;
            }
        }

        private Style m_style;
        /// <summary>
        /// Style of the Grid
        /// </summary>
        public Style Style
        {
            get
            {
                if (m_style == null)
                    m_style = new Style();
                return m_style;
            }
        }

		int m_schemaid;
		public int SchemaID{
			get{
				if(m_schemaid <=0)
					m_schemaid = PlanData.GetPlanSchemaID(PlanID);
				return m_schemaid;
			}
		}

		string m_schemaname = string.Empty;
		public string SchemaName
		{
			get
			{
				if (m_schemaname == string.Empty)
					m_schemaname = PlanData.GetSchemaName(SchemaID);
				return m_schemaname;
			}
		}

        int showDays = -1;
        bool ShowDaysInPlan
        {
            get
            {
                if (showDays < 0)
                    showDays = Gencode.PrsCommon.App.PlanOption.ShowDaysInPlan;

                if (showDays == 0)
                    return false;
                if (showDays == 1)
                    return true;
                return false;
            }
        }
    }
}
